/**
 * 
 */
package org.jfarrell.gui;

import javax.swing.*;

import javax.media.util.*;

import java.awt.*;
import java.awt.event.*;
import java.io.ObjectOutputStream;
import java.net.Socket;

import javax.media.*;
import javax.media.format.*;
import javax.media.control.*;

import org.jfarrell.classes.Command;


/**
 * @author Jason Farrell
 * @version 1.0.0
 * @date 2/1/2007
 * 
 * This is the main GUI - containing the Image and Init Button for the Applicationm
 * The Image acts as a Label with a MouseListener.  When it is clicked a snap shot is taken
 * from the webcam and sent to the server along with the point that was clicked
 *
 */
public class FrmMain extends JFrame implements ControllerListener, MouseListener, ActionListener
{	
	private Player m_player = null;
	private Component m_visual = null;
	
	private Container m_pane = null;
	
	private String m_ipAddress;
	private String m_port;
	private String m_destIp;
	private int m_destPort;
	
	private JTextField m_moveDistance = new JTextField(6);
	private JTextField m_rotateAmt = new JTextField(3);
	
	// other needed instances
	private boolean m_clickable = true;
	
	public FrmMain( String pIp, String pPort, String destIp, String destPort )
	{
		super( "Video Receiver" );
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		//this.setSize(640, 480);
		
		this.m_ipAddress = pIp;
		this.m_port = pPort;
		this.m_destIp = destIp;
		this.m_destPort = Integer.parseInt(destPort);
		
		this.m_pane = this.getContentPane();
		this.m_pane.setLayout( new BoxLayout(this.m_pane, BoxLayout.Y_AXIS) );
		this.setupAndRealizePlayer();
		
		// Build the GUI
		this.m_pane.add( this.buildPanel() );
		this.m_pane.add( this.BuildControlInterface() );
		
		// make visible
		this.setVisible( true );
		this.pack();
	}
	
	private JPanel BuildControlInterface()
	{
		JPanel p = new JPanel();
		p.setLayout( new BoxLayout(p, BoxLayout.Y_AXIS) );
		JPanel inner_pane = new JPanel();
		JButton submit_button = new JButton("Move Robot");
		
		// add the move button
		inner_pane.setLayout( new FlowLayout(FlowLayout.LEFT) );
		inner_pane.add( new JLabel("Move: ") );
		inner_pane.add( this.m_moveDistance );
		inner_pane.add( new JLabel("cm") );
		submit_button.setActionCommand("move");
		submit_button.addActionListener(this);
		inner_pane.add( submit_button );
		p.add( inner_pane );
		
		// add the rotate button
		inner_pane = new JPanel();
		inner_pane.setLayout( new FlowLayout(FlowLayout.LEFT) );
		inner_pane.add( new JLabel("Rotate: ") );
		inner_pane.add( this.m_rotateAmt );
		inner_pane.add( new JLabel("degrees") );
		submit_button = new JButton("Rotate");
		submit_button.setActionCommand("rotate");
		submit_button.addActionListener(this);
		inner_pane.add( submit_button );
		p.add( inner_pane );
		
		return p;
	}
	
//	 main gui builder
	private JPanel buildPanel()
	{
		JPanel p = new JPanel();
		p.setLayout( new FlowLayout( FlowLayout.CENTER ) );
		
		while (this.m_visual == null) ;	// busy wait
		p.add( this.m_visual );
		
		return p;
	}
	
	// setup and realize the player
	private void setupAndRealizePlayer()
	{
		// create the media locator
		String locator = "rtp://" + this.m_ipAddress + ":" + this.m_port + "/video/1";
		System.out.println(locator);
		MediaLocator locate = new MediaLocator(locator);
		if (locate == null) {
			System.out.println("Failed Creating the Locator");
			System.exit(0);
		}
		
		// create the player
		try
		{
			this.m_player = Manager.createPlayer(locate);
		}
		catch (Exception ex) {
			System.out.println( ex.getMessage() );
			System.exit(0);
		}
		
		// set the player properties
		this.m_player.addControllerListener(this);
		this.m_player.realize();
	}
	
	// handle control events
	public void controllerUpdate(ControllerEvent ev)
	{
		if ( ev instanceof RealizeCompleteEvent ) {
			this.m_player.start();
			//this.m_isRealized = true;
			this.m_visual = this.m_player.getVisualComponent();
			this.m_visual.addMouseListener(this);
		}
	}
	
	public void actionPerformed( ActionEvent ev )
	{
		try
		{
			Socket sock = new Socket( this.m_destIp, this.m_destPort );
			ObjectOutputStream outStream = new ObjectOutputStream( sock.getOutputStream() );
			outStream.flush();
			
			Command com = null;
			if ( ev.getActionCommand() == "move" )
			{
				com = new Command( Command.GO, Integer.parseInt(this.m_moveDistance.getText()) );
			}
			else if (ev.getActionCommand() == "rotate" )
			{
				com = new Command( Command.TURN, Integer.parseInt(this.m_rotateAmt.getText()));
			}
			
			outStream.writeObject(com);
			outStream.close();
		}
		catch (java.io.IOException ex) {
			System.out.println( ex.getMessage() );
		}
	}
	
	/**
	 * Mouse Listener Event Handlers
	 */
	
	public void mousePressed(MouseEvent e) {
		// method not used
	}
	
	public void mouseReleased(MouseEvent e) {
		// method not used
	}
	
	public void mouseEntered(MouseEvent e) {
		// method not used
	}
	
	public void mouseExited(MouseEvent e) {
		// method not used
	}
	
	public void mouseClicked(MouseEvent e) {
		//this.m_player.stop();
		//JOptionPane.showMessageDialog(this, "X: " + e.getX() + " Y: " + e.getY());
		
		// get the still image and prepare to send it
		if (this.m_clickable)
		{
			Buffer bufferFrame;
			BufferToImage bufferToImage;
			Image image;
			/*
			 * This code extracted from JMStudio
			 */
			
			bufferFrame =
				((FrameGrabbingControl)this.m_player.getControl("javax.media.control.FrameGrabbingControl")).grabFrame();
			bufferToImage = new BufferToImage ( (VideoFormat)bufferFrame.getFormat() );
			image = bufferToImage.createImage ( bufferFrame );
			
			/*
			 * Socket to the Test Server ( for now ) and send the Image
			 */
			try
			{
				Socket sock = new Socket( this.m_destIp, this.m_destPort );
				ObjectOutputStream outStream = new ObjectOutputStream( sock.getOutputStream() );
				outStream.flush();
				
				Command pi = new Command( image, e.getPoint() );
				outStream.writeObject( pi );
				outStream.close();
			}
			catch (java.io.IOException ex) {
				System.out.println( ex.getMessage() );
			}
		}
		
		// set clickable to false - disallow further clicks until path finding is done
		this.m_clickable = false;
	}
	
	// entry point for debugging - remove this when the main program starter class is created
	public static void main(String[] args)
	{
		String monitorIp, monitorPort, connectIp, connectPort;
		if (args.length != 4) {
			System.out.println( "Format: java FrmMain <this_ip> <port> <main server ip>" );
			System.exit(0);
		}
		else {
			FrmMain main_program = new FrmMain( args[0], args[1], args[2], args[3] );
		}
	}
}
